/* main.c */
#include "app_inc.h"

/*
* Application Function Declerations.
*/
/* LED. */
void LED_Configuration(void);
void LED_LightOn(uint32_t ledIdx);
void LED_LightOff(uint32_t ledIdx);
/* Button. */
void BTN_Configuration(void);
bool BTN_IsPressedDown(uint32_t btnIdx);

/*
* Application Entry.
*/
int main(void)
{
    BSP_InitStdioUART(115200U);

    printf("\r\n\r\n# GPIO_EdgeInterrupt Example r#\r\n");

    /* Initialize the application. */
    printf("# Initializing ...\r\n");
    
    LED_Configuration();
    BTN_Configuration();
    
    printf("# Ready.\r\n");
    
    /* Print the user guide. */
    printf("# Press the buttons to turn on the LEDs ...\r\n");
    
    while (1)
    {
        __ASM("WFI");
    }
}

void LED_Configuration(void)
{
    GPIO_InitPara GPIO_InitStructure;
    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOD,ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_11 | GPIO_PIN_12|GPIO_PIN_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
    GPIO_Init(GPIOD,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_11 | GPIO_PIN_12 |GPIO_PIN_13;
    GPIO_Init(GPIOD,&GPIO_InitStructure);
}

const uint16_t gLedPins[] = {GPIO_PIN_11, GPIO_PIN_12, GPIO_PIN_13}; 

void LED_LightOn(uint32_t ledIdx)
{
    if (ledIdx >= sizeof(gLedPins)/sizeof(gLedPins[0]))
    {
        return;
    }
    GPIO_SetBits(GPIOD, gLedPins[ledIdx]);
}

void LED_LightOff(uint32_t ledIdx)
{
    if (ledIdx >= sizeof(gLedPins)/sizeof(gLedPins[0]))
    {
        return;
    }
    GPIO_ResetBits(GPIOD, gLedPins[ledIdx]);
}

void BTN_Configuration(void)
{
    GPIO_InitPara GPIO_InitStructure;
    EXTI_InitPara EXTI_InitStructure;
    NVIC_InitPara NVIC_InitStructure;
    
    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOD ,ENABLE);

    /* Configure PD14/15 pin */
    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_14|GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* Connect EXTI Line 14 to PC14 pin */
    GPIO_EXTILineConfig(GPIO_PORT_SOURCE_GPIOD, GPIO_PINSOURCE15);
    /* Connect EXTI Line 15 to PC15 pin */
    GPIO_EXTILineConfig(GPIO_PORT_SOURCE_GPIOD, GPIO_PINSOURCE14);

    /* Configure EXTI Line 0 and its interrupt to the lowest priority*/
    EXTI_InitStructure.EXTI_LINE = EXTI_LINE14 | EXTI_LINE15;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /* Trigger by falling edge. */
    EXTI_InitStructure.EXTI_LINEEnable = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQ = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQPreemptPriority = 0;
    NVIC_InitStructure.NVIC_IRQSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

const uint16_t gBtnPins[] = {GPIO_PIN_14, GPIO_PIN_15};

bool BTN_IsPressedDown(uint32_t btnIdx)
{
    if (btnIdx >= sizeof(gBtnPins)/sizeof(gBtnPins[0]))
    {
        return false;
    }
    if (RESET == GPIO_ReadInputBit(GPIOD, gBtnPins[btnIdx]))
    {
        return true;
    }
    else
    {
        return false;
    }
}

uint32_t BTN_ScanKey(void)
{
    int count = 0xffff;

    if (EXTI_GetIntBitState(EXTI_LINE14) != RESET) /* Check the interrupt flag. */
    {
        while(count--);
        if (EXTI_GetIntBitState(EXTI_LINE14) != RESET)
        {
            EXTI_ClearIntBitState(EXTI_LINE14);
            return 1U; /* Key1. */
        }
    }
    
    if (EXTI_GetIntBitState(EXTI_LINE15) != RESET) /* Check the interrupt flag. */
    {
        while(count--);
        if (EXTI_GetIntBitState(EXTI_LINE15) != RESET)
        {
            EXTI_ClearIntBitState(EXTI_LINE15);
            return 2U; /* Key2. */
        }
    }
    return 0U;
}

void EXTI15_10_IRQHandler(void)
{
    uint32_t keyValue = BTN_ScanKey();

    if (1U == keyValue)
    {
        LED_LightOn(0U);
        LED_LightOn(1U);
        LED_LightOn(2U);
    }
    else if (2U == keyValue)
    {
        LED_LightOff(0U);
        LED_LightOff(1U);
        LED_LightOff(2U);
    }
}

/* EOF. */
